/**
 *  三种策略：
 * 
 *  setInterval(() => {}, 16)

    let tick = () => {
        setTimeout(tick, 16)
    }

    let tick = () => {
        requestAnimationFrame(tick)
    }
 */
const TICK = Symbol("tick");
const TICK_HANDLER = Symbol("tick-handler");
const ANIMATIONS = Symbol("animations");
const START_TIME = Symbol("start-time");
const PAUSE_START = Symbol("pause-start");
const PAUSE_TIME = Symbol("pause-time");

export class Timeline {
    constructor() {
        this[ANIMATIONS] = new Set();
        this[START_TIME] = new Map();
    }
    start() {
        const startTime = Date.now();
        this[TICK] = () => {
            console.log("tick")
            const now = Date.now();
            for (let animation of this[ANIMATIONS]) {
                let t;
                if (this[START_TIME].get(animation) < startTime) {
                    t = now - startTime;
                } else {
                    t = now - this[START_TIME].get(animation)
                }

                if (animation.duration < t) {
                    this[ANIMATIONS].delete(animation);
                    t = animation.duration;
                }
                animation.receive(t)
            }
            requestAnimationFrame(this[TICK]);
        }
        this[TICK]();
    }

    // set rate() {}
    // get rate() {}

    pause() {
        this[PAUSE_START] =  Date.now();
        cancelAnimationFrame(this[TICK_HANDLER]);
    }

    resume() {
        THIS[PAUSE_TIME] += Date.now() - this[PAUSE_START];
        this[TICK]();
    }

    reset() {}

    add(animation, startTime) {
        if (arguments.length < 2) {
            startTime = Date.now();
        }
        this[ANIMATIONS].add(animation);
        this[START_TIME].set(animation, Date.now());
    }
}

export class Animation {
    constructor(object, property, startValue, endValue, duration, delay, timingFunction, template) {
        this.object = object;
        this.property = property;
        this.startValue = startValue;
        this.endValue = endValue;
        this.duration = duration;
        this.delay = delay;
        this.timingFunction = timingFunction;
        this.template = template;
    }

    receive(time) {
        console.log(time);
        const range = this.endValue - this.startValue;
        this.object[this.property] = this.startValue + range * time / this.duration
    }
}